// 当前实现的是 history 模式 


//根据url显示对应的内容
//监听一个变量current -> 利用数据响应式，当current变化的时候
//每一个组件都有一个render函数执行的结果-> 得到vdom虚拟dom ->得到真实dom


// 3.实现install方法:vue.use方法就是 调用了install方法
// $router 注册
// 两个全局组件

let Vue // 引用构造函数 VueRouter中要用


//1.实现一个插件
//2.实现VueRouter：处理路由选项；监控url变化,hashchange；响应这个变化，动态渲染
class VueRouter {

  constructor(options) {
    // 保存选项
    this.options = options
    //保存路径地址与组件之间的映射关系
    this.routeMap = {}
    //构建响应式属性 
    this.data = Vue.observable({
      current: '/'
    })
  }

  init () {
    this.createRouteMap()
    this.initComponents(Vue)
    this.initEvent()
  }

  createRouteMap () {
    //遍历所有的路由规则，把路由规则解析成键值对的形式，存储到routeMap中。
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component
    });
  }

  initComponents (Vue) {
    Vue.component('router-link', {
      props: {
        to: {
          type: String,
          required: true
        }
      },
      render (h) {
        //<router-link to="#/about">abc</router-link>
        return h('a', {
          attrs: {
            href: this.to
          },
          on: {
            click: this.clickHandler
          }
        }, [this.$slots.default]) //插槽slots
      },
      methods: {
        clickHandler (e) {
          history.pushState({}, '', this.to)
          this.$router.data.current = this.to
          e.preventDefault()
        }
      }
    })

    const that = this
    Vue.component('router-view', {
      render (h) {
        let component = null
        if (that.data.current) {
          component = that.routeMap[that.data.current];
        }
        return h(component)
      }
    })
  }

  initEvent () {
    window.addEventListener('popstate', () => {
      this.data.current = window.location.pathname
    })
  }

}

// 插件要求实现install（vue调用use的时候，这里会传一个vue的构造函数）
VueRouter.install = function (_vue) {
  if (VueRouter.install.installed) { //判断当前插件是否已经被安装
    return
  }

  VueRouter.install.installed = true
  console.log('VueRouter is installed success');
  Vue = _vue;
  Vue.mixin({
    beforeCreate () {
      //挂载$router, 以后每一个组件都会调用这个方法。
      if (this.$options.router) {
        //只有根实例new Vue的时候才会进入该逻辑。
        //此时的上下文this.是当前组件实例
        Vue.prototype.$router = this.$options.router
        this.$options.router.init();
      }
    }
  })
}

export default VueRouter